package file;

import file.config.FsConfig;
import file.config.MyConfigProperties;
import file.util.FileInfoUtil;
import file.util.FileUtil;
import file.util.IdUtil;
import file.util.IpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author hh
 * @since 2024/12/4
 */
@RestController
public class FileController {

    private final Logger log = LoggerFactory.getLogger(FileController.class);
    private final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private final DateTimeFormatter windowsDtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒");

    private final MyConfigProperties myConfigProperties;

    public FileController(MyConfigProperties myConfigProperties) {
        this.myConfigProperties = myConfigProperties;
    }

    @PostMapping("upload")
    public String upload(MultipartFile file) {
        try {
            String originalFilename = file.getOriginalFilename();
            if (Objects.isNull(originalFilename)) {
                return "文件名不能为空";
            }
            if (originalFilename.contains(FileUtil.SEP)) {
                return "文件名中不能含有“" + FileUtil.SEP + "”";
            }
            FileUtil.deleteFileByFileName(originalFilename);
            String id = IdUtil.getId();
            String osName = System.getProperty("os.name");
            String fileName;
            if (osName.contains("Windows")) {
                fileName = id + FileUtil.SEP + originalFilename + FileUtil.SEP + LocalDateTime.now().format(windowsDtf);
            } else {
                fileName = id + FileUtil.SEP + originalFilename + FileUtil.SEP + LocalDateTime.now().format(dtf);
            }
            FileUtil.saveFile(file.getInputStream(), fileName);
            FsConfig.save(id, "");
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return "上传失败：" + e.getMessage();
        }
        return "上传成功";
    }

    @GetMapping(value = "/view/{name}")
    public void view(@PathVariable("name") String name,
                     @RequestParam(value = "id", required = false) String id,
                     HttpServletResponse response) throws Exception {
        if (!StringUtils.hasText(id) && !StringUtils.hasText(name)) {
            log.error("文件id或文件名称不能为空");
            return;
        }
        List<String> fileList = FileUtil.ls();
        String resourceName = null;
        for (String resource : fileList) {
            if ((StringUtils.hasText(id) && resource.startsWith(id + FileUtil.SEP))
            || (StringUtils.hasText(name) && resource.contains(name + FileUtil.SEP))) {
                resourceName = resource;
                break;
            }
        }
        if (resourceName == null) {
            log.error("读取文件失败！文件可能不存在");
            return;
        }
        String fileName = resourceName.split(FileUtil.SEP)[1];
        if (fileName.endsWith(".pdf")) {
            response.setContentType(MediaType.APPLICATION_PDF_VALUE);
        } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
            response.setContentType(MediaType.IMAGE_JPEG_VALUE);
        } else if (fileName.endsWith(".gif")) {
            response.setContentType(MediaType.IMAGE_GIF_VALUE);
        } else if (fileName.endsWith(".png")) {
            response.setContentType(MediaType.IMAGE_PNG_VALUE);
        } else if (fileName.endsWith(".md")) {
            response.setContentType("text/markdown;charset=UTF-8");
        } else if (fileName.endsWith(".docx") || fileName.endsWith(".doc")) {
            response.setContentType("application/msword");
        } else if (fileName.endsWith(".html") || fileName.endsWith(".htm")){
            response.setContentType(MediaType.TEXT_HTML_VALUE);
        } else if (fileName.endsWith(".xml")) {
            response.setContentType(MediaType.TEXT_XML_VALUE);
        } else if (fileName.endsWith(".txt")) {
            response.setContentType("text/plain;charset=UTF-8");
        } else {
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        }
        FileUtil.writeOutPutStream(response.getOutputStream(), resourceName);
    }

    @GetMapping("fileList")
    public List<FileInfo> fileList() {
        try {
            List<String> ls = FileUtil.ls();
            List<FileInfo> fileInfos = new ArrayList<>();
            for (String fileInfoStr : ls) {
                if (StringUtils.hasText(fileInfoStr)) {
                    // 跳过隐藏文件
                    if (fileInfoStr.startsWith(".")) {
                        continue;
                    }
                    String[] fileInfoSplit = fileInfoStr.split(FileUtil.SEP);
                    FileInfo fileInfo = FileInfoUtil.getFileInfo(fileInfoSplit);
                    if (fileInfo != null) {
                        fileInfos.add(fileInfo);
                    }
                }
            }
            List<FileInfo> nullUploadTimeFileInfoList = fileInfos.stream()
                    .filter(m -> Objects.isNull(m.getUploadTime()))
                    .collect(Collectors.toList());
            fileInfos.removeAll(nullUploadTimeFileInfoList);
            fileInfos.sort(Comparator.comparing(FileInfo::getUploadTime));
            fileInfos.addAll(nullUploadTimeFileInfoList);
            return fileInfos;
        } catch (Exception e) {
            log.error("查看文件列表失败", e);
            return Collections.emptyList();
        }
    }

    @PostMapping("deleteFile")
    public String deleteFile(String id) {
        try {
            FsConfig.delete(id);
            boolean deleted = FileUtil.deleteFileById(id);
            if (deleted) {
                return "0";
            }
            return "1";
        } catch (Exception e) {
            log.error("删除文件[{}]失败", id, e);
            return "1";
        }
    }

    @GetMapping("isShowUpdatePwd")
    public String isShowUpdatePwd() {
        if (myConfigProperties.isEnableLogin()) {
            return "1";
        }
        return "0";
    }

    @GetMapping("isShowUpdateWhiteList")
    public String isShowUpdateWhiteList(HttpServletRequest request) throws Exception {
        String managerIp = FsConfig.get(Constant.MANAGER_IP);
        if (StringUtils.hasText(managerIp)) {
            List<String> managerIpList = Arrays.asList(managerIp.split(","));
            String ip = IpUtil.getClientIp(request);
            if (managerIpList.contains(ip)) {
                return "1";
            }
        }
        return "0";
    }

    @GetMapping("getWhiteList")
    public String getWhiteList(@RequestParam(value = "id", required = false) String id) throws Exception {
        if (StringUtils.hasText(id)) {
            return FsConfig.get(id);
        }
        return FsConfig.get(Constant.IP_WHITE_LIST);
    }

    @PostMapping("updateWhiteList")
    public String updateWhiteList(@RequestParam(value = "id",required = false) String id,
                                  @RequestParam("whiteList") String whiteList) throws Exception {
        if (StringUtils.hasText(id)) {
            FsConfig.save(id, whiteList);
        } else {
            FsConfig.save(Constant.IP_WHITE_LIST, whiteList);
        }
        return "1";
    }

}
